/**
 * @author shahma
 */
dojo.provide("medryx.orm.internal.ManagedProperty");


/**
 * Remember, these "properties" are SHARED BETWEEN ALL INSTANCES OF AN ENTITY-CLASS
 * @param {Object} kwArguments
 */
dojo.declare("medryx.orm.internal.ManagedProperty", null, {
	constructor:function(kwArguments) {
		dojo.mixin(this, kwArguments);
		this.deferreds = {};
	},
	
	/**
	 * initialize this property given a value.
	 * this is the most basic implementation, and will likely
	 * be over-ridden in subclasses.
	 * 
	 * @param {Object} instance
	 * @param {Object} propertyName
	 * @param {Object} value
	 */
	initialize:function(instance, propertyName, value, entityManager) {
		instance[propertyName] = value;
	},
	
	isReadOnly:function() {
		return this.readOnly === true;
	},
	
	isEager:function() {
		return this.lazy === false || this.eager === true;
	},
	
	/**
	 * load the value and return a deferred. not that subsequent calls to
	 * this method should return the SAME INSTANCE of deferred as the first
	 * call. Note that upon return from this deferred you should 
	 * guarantee that the property requested is set (though you may, and
	 * probably should set more than one property).
	 */
	loadValueDeferred:function(instance, sync) {
		var service = this.entityManager.getPersistenceService(instance);
		var entityManager = this.entityManager;
		var propertyName = this.propertyName;
		var deferred = this.deferreds[instance.id];
		
		if (!deferred) {
			deferred = service.load(this.entityManager.getClassName(instance), this.entityManager.getIdentifier(instance), [this.propertyName], sync);
			
			deferred.addCallback(function(bag){
				entityManager.populateInstance(instance, bag);
				return instance[propertyName];
			});
		}
		var defToReturn = new dojo.DeferredList([deferred]);
		defToReturn.addCallback(function() {
			return instance[propertyName];
		});
		
		return defToReturn;
		
	},
	
	//TODO: implement optional clobber protection
	set:function(instance, propertyName, value, dontClobber) {
		if (!dontClobber) {
			instance[propertyName] = value;
		} else {
			var currentValue = instance[propertyName];
			if (typeof(currentValue) === "undefined" || currentValue === null || currentValue instanceof medryx.orm.internal.ManagedProperty) {
				instance[propertyName] = currentValue;
			} else {
				console.info("protecting entity from clobbering by property initializer:", instance, propertyName, value);
			}
		} 
	},
	
	toString:function() {
		return this.declaredClass;
	}
});
